package win.larryzeal.jmx.util;

import win.larryzeal.jmx.mbean.model.Eat;

import javax.management.Descriptor;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.modelmbean.RequiredModelMBean;

/**
 * Created by 张少昆 on 2017/8/18 0018.
 */
public class ModelMBeanUtils {
	private static final boolean READABLE = true;
	private static final boolean WRITABLE = true;
	private static final boolean BOOLEAN = true;
	private static final String STRING_CLASS = "java.lang.String";

	public static RequiredModelMBean createModelerMBean(){
		RequiredModelMBean model = null;
		try{
			model = new RequiredModelMBean();
			model.setManagedResource(new Eat(), "ObjectReference");
			ModelMBeanInfo info = createModelMBeanInfo();
			model.setModelMBeanInfo(info);
		} catch(Exception e){
			e.printStackTrace();
		}
		return model;
	}

	private static ModelMBeanInfo createModelMBeanInfo(){
		//////////////////////////////////////////////////////////////////
		//                        属性                                  //
		//////////////////////////////////////////////////////////////////
		// 构造name属性信息
		Descriptor foodDescriptor = new DescriptorSupport();
		foodDescriptor.setField("name", "Food");
		foodDescriptor.setField("descriptorType", "attribute");
		foodDescriptor.setField("displayName", "Food");//卧槽？
		foodDescriptor.setField("getMethod", "getFood");//卧槽？
		foodDescriptor.setField("setMethod", "setFood");//卧槽？
		ModelMBeanAttributeInfo foodModelMBeanAttributeInfo = new ModelMBeanAttributeInfo(//
				"Food", // 属性名
				STRING_CLASS, // 属性类型
				"food name", // 描述文字
				READABLE, WRITABLE, !BOOLEAN, // 读写
				foodDescriptor // 属性描述
		);

		// TODO 为什么setter/getter也要描述？？？
		//////////////////////////////////////////////////////////////////
		//                        方法                                  //
		//////////////////////////////////////////////////////////////////
		// 构造 getFood操作 描述符信息
		Descriptor getFoodDescriptor = new DescriptorSupport(new String[]{
				"name=getFood",
				"descriptorType=operation",
				"class=win.larryzeal.jmx.mbean.model.Eat", // 卧槽？
				"role=operation"
		});

		ModelMBeanOperationInfo getFoodModelMBeanOperationInfo = new ModelMBeanOperationInfo(//
				"getFood", //
				"get the food", //
				null, //
				"java.lang.String", //
				MBeanOperationInfo.INFO, //
				getFoodDescriptor //
		);

		// 构造 setFood操作 描述符信息
		Descriptor setFoodDescriptor = new DescriptorSupport(new String[]{
				"name=setFood",
				"descriptorType=operation",
				"class=win.larryzeal.jmx.mbean.model.Eat",
				"role=operation"});

		MBeanParameterInfo[] setFoodMBeanParameterInfos = new MBeanParameterInfo[]{(new MBeanParameterInfo(
				"food", // TODO 这是？
				STRING_CLASS,
				"new food name"))};

		ModelMBeanOperationInfo setFoodModelMBeanOperationInfo = new ModelMBeanOperationInfo(//
				"setFood", //
				"set food attribute", //
				setFoodMBeanParameterInfos, //
				"void", //
				MBeanOperationInfo.ACTION, //
				setFoodDescriptor // TODO 不需要吗
		);

		//构造 comment()操作的信息
		ModelMBeanOperationInfo commentModelMBeanOperationInfo = new ModelMBeanOperationInfo(//
				"comment", //
				null, //
				null, //
				"void", //
				MBeanOperationInfo.INFO, //
				null // TODO 不需要吗
		);
		// 构造comment(String food)操作信息
		MBeanParameterInfo[] param2 = new MBeanParameterInfo[]{ new MBeanParameterInfo(
				"comment",
				STRING_CLASS,
				"comment the given food")};
		ModelMBeanOperationInfo comment2Info = new ModelMBeanOperationInfo(//
				"comment", //
				null,//
				param2,//
				"void", //
				MBeanOperationInfo.INFO, //
				null // TODO 不需要吗
		);
		//////////////////////////////////////////////////////////////////
		//                        最后总合                              //
		//////////////////////////////////////////////////////////////////
		// create ModelMBeanInfo
		ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport(//
				RequiredModelMBean.class.getName(), // MBean类
				null, // 描述文字
				new ModelMBeanAttributeInfo[]{ foodModelMBeanAttributeInfo},// 所有的属性信息（数组）。这里只有一个属性
				null, // 所有的构造函数信息
				new ModelMBeanOperationInfo[]{ // 所有的操作信息（数组）
						getFoodModelMBeanOperationInfo,
						setFoodModelMBeanOperationInfo,
						commentModelMBeanOperationInfo,
						comment2Info},//
				null, // 所有的通知信息(本例无)
				null//MBean描述
		);
		return mbeanInfo;
	}
}
